home *** CD-ROM | disk | FTP | other *** search
- /* eyes.c
-
- A just-for-fun accessory. It really looks where the mouse is.
- A public domain program by
-
- Peter Kirchgessner
- Laubenheimer Str. 78
- D W6500 Mainz-Weisenau
- Federal Republic of Germany
-
- for Atari ST (monochrome/color).
- Tested with Megamax Laser C V 2.0
- Borland Turbo C V 2.0
-
- Idea by Silicon Graphics.
-
- Created : 10-Feb-91 V 0.01
- Last change : 31-Mar-91 V 1.00
- */
- /* Description : This accessory opens automatically a window
- where two eyes are displayed. These eyes are looking in
- direction to the mouse pointer. The positions of the pupils
- are updated every 0.15 sec (only on change). With a single
- click inside the window it will become the top window.
- Then it can be moved by pressing the left mouse button
- when inside the window and hold it down during move.
- With a double click, the window is closed and it will no
- longer automatically open after start or end of a program.
- When activating the accessory via its menu entry, automatic
- open is re-enabled.
- If the window is totally covered, the accessory tries to
- find an area where it can look through. Then the window is
- moved to that location.
- */
-
- #ifdef __TURBOC__
- /* These includes for Turbo C (__TURBOC__ is predefined) */
-
- #include <aes.h>
- #include <vdi.h>
- #include <stdlib.h>
-
- #else
- /* Otherwise Laser C needs these ones */
-
- #include <obdefs.h>
- #include <gemdefs.h>
-
- int contrl[15],intin[128],ptsin[128],intout[128],ptsout[128];
- /* The following is special for Laser C. */
- /* We dont need the default 8KB stack. */
- long _stksize = 1400L;
-
- #endif
-
- #define max(a,b) (((a) > (b)) ? (a) : (b))
- #define min(a,b) (((a) < (b)) ? (a) : (b))
- #define NOT_VALID 32000
- #define TRUE 1
- #define FALSE 0
-
- /* Size of work area of window */
- #define WORK_WIDTH 52
- #define WORK_HEIGHT 42
-
- /* Define SHOW_ACTIVITY to invert a 2x2 rectangle at position
- (0,0) on each activation of the accessory
- */
- /*
- #define SHOW_ACTIVITY
- */
- /* Pseudo-random number generator */
- static int myrand = 1; /* Startvalue */
- #define RAND() (myrand = (myrand * 16017 + 1) & 0x7fff)
-
- /* Position of eyes from center of work area */
- #define EYE_DX 9
- #define EYE_DY 7
-
- /* The following variables can be found in the .ACC file */
- /* by searching for the 4 byte hexadecimal magic number. */
- /* This allows some modifications of the program without */
- /* compiling the source (position of window at start, */
- /* window components, automatic open after start) */
-
- static long magic = 0x31415926L; /* Magic for following data */
-
- static int work_x_origin = 85; /* Origin of own windows work area */
- static int work_y_origin = 20; /* within Desktop work area */
-
- /* Components of window: 0 or 11 */
- static int win_components = 0; /* or (NAME | CLOSER | MOVER) */
-
- static int auto_open = TRUE; /* Flag for automatic open of accessory */
-
- /* global variables */
-
- extern int _app; /* Application-flag */
- static int handle; /* handle for VDI routines */
-
- #define MENU_ENTRY " Eyes "
-
- /*** Variables for window-handling ***/
- /* Handle of open window (<= 0: window not open) */
- static int whandle;
-
- /* Handles for GEM and VDI */
- static int appl_id,menu_id;
-
- static int desk_work[4]; /* Desktop work area as rectangle */
- static int desk_size[2]; /* Width and height of desktop work area */
-
- static int mouse_x,mouse_y, /* current and last mouse position */
- last_x = NOT_VALID,last_y = NOT_VALID;
-
-
- typedef struct /* Position of pupils of eyes */
- {
- int left_dx;
- int right_dx;
- int dy;
- } EYE_DATA;
-
- static EYE_DATA new_eye,
- last_eye = {NOT_VALID,NOT_VALID,NOT_VALID};
-
- #ifdef __TURBOC__
-
- /* Prototypes for Turbo C */
- static void position (int mdx,int mdy,int *dx,int *dy);
- static int new_position (int mousex,int mousey);
- static void save_position (void);
- static void eyes (EYE_DATA *eye);
- static void face (void);
- static void open_window (int use_grow_box);
- static void open_back_window (int use_grow_box);
- static void close_window (int use_shrink_box);
- static void move_window (int x,int y);
- static int rect_intersect (GRECT *rec1,GRECT *rec2);
- static void redraw_window (int all);
- static int handle_message (int pipe[8]);
- static void event_loop (void);
-
- #endif
-
-
- /* Calculate position of a pupil
-
- Input:
- int mdx,mdy : direction to position of mouse
- from center of eye
- Output:
- int *dx,*dy : direction of pupil from center of eye
-
- The position of the pupil is within an 9 x 11 rectangle
- around the center of the eye.
- */
-
- static void position (mdx,mdy,dx,dy)
- int mdx,mdy,*dx,*dy;
-
- {int adx,ady,m;
- /* Evaluate maximum absolute value of mdx and mdy */
- adx = (mdx < 0) ? (-mdx) : mdx;
- ady = (mdy < 0) ? (-mdy) : mdy;
- m = max (adx,ady);
-
- if (m) /* Not zero ? Evaluate point within 9 x 11 rectangle */
- {
- mdx *= 4; mdy *= 5;
- *dx = mdx / m; *dy = mdy / m;
- }
- else /* Mouse is on center of eye */
- *dx = *dy = 0;
- }
-
-
- /* Calculate position of pupils from mouse position
-
- Input:
- int mousex,mousey : position of mouse
-
- The position of the pupils is stored in variable new_eye.
- The function returns TRUE if the position of the pupils has
- changed, otherwise FALSE is returned.
- */
-
- static int new_position (mousex,mousey)
- int mousex,mousey;
-
- {int work_x_center,work_y_center;
- int mouse_dx,mouse_dy;
- int left_dy,right_dy;
- /* center of work area */
- work_x_center = work_x_origin + (WORK_WIDTH >> 1);
- work_y_center = work_y_origin + (WORK_HEIGHT >> 1);
- /* direction to mouse position */
- mouse_dx = mousex - work_x_center;
- mouse_dy = mousey - work_y_center;
- /* Position of pupil of left eye */
- position (mouse_dx+EYE_DX,mouse_dy+EYE_DY,
- &(new_eye.left_dx),&left_dy);
- /* Position of pupil of right eye */
- position (mouse_dx-EYE_DY,mouse_dy+EYE_DY,
- &(new_eye.right_dx),&right_dy);
- /* Pupils should have the same y-position */
- new_eye.dy = (left_dy + right_dy) >> 1;
- /* Check if position has changed */
- return ( new_eye.left_dx != last_eye.left_dx
- || new_eye.right_dx != last_eye.right_dx
- || new_eye.dy != last_eye.dy);
- }
-
-
- /* Save current position of pupils
- */
-
- static void save_position ()
-
- {last_eye.left_dx = new_eye.left_dx;
- last_eye.right_dx = new_eye.right_dx;
- last_eye.dy = new_eye.dy;
- }
-
-
- /* Draw pupils at given position
-
- Input:
- EYE_DATA *eye : structure with position of pupils
- */
-
- static void eyes (eye)
- EYE_DATA *eye;
-
- {register int work_x_center,work_y_center;
- int xy[4];
- int left_eye_x,left_eye_y;
- int right_eye_x,right_eye_y;
- /* center of work area */
- work_x_center = work_x_origin + (WORK_WIDTH >> 1);
- work_y_center = work_y_origin + (WORK_HEIGHT >> 1);
-
- left_eye_x = work_x_center - EYE_DX; /* center of eyes */
- right_eye_x = work_x_center + EYE_DX;
- left_eye_y = right_eye_y = work_y_center - EYE_DY;
-
- xy[0] = left_eye_x + eye->left_dx - 1; /* rectangle representing */
- xy[1] = left_eye_y + eye->dy - 2; /* pupil of left eye */
- xy[2] = left_eye_x + eye->left_dx + 1;
- xy[3] = left_eye_y + eye->dy + 2;
- vr_recfl (handle,xy);
-
- xy[0] = right_eye_x + eye->right_dx - 1; /* dito right eye */
- xy[1] = right_eye_y + eye->dy - 2;
- xy[2] = right_eye_x + eye->right_dx + 1;
- xy[3] = right_eye_y + eye->dy + 2;
- vr_recfl (handle,xy);
- }
-
-
- /* Draw background of window
- Fill the window, draw eye-ellipses
- */
-
- static void face ()
-
- {int rect[4];
- int xc,yc;
-
- rect[0] = work_x_origin; /* Work area rectangle */
- rect[1] = work_y_origin;
- rect[2] = work_x_origin + WORK_WIDTH;
- rect[3] = work_y_origin + WORK_HEIGHT;
-
- /* Center of work area */
- xc = work_x_origin + (WORK_WIDTH >> 1);
- yc = work_y_origin + (WORK_HEIGHT >> 1);
-
- vsf_color (handle,0); /* white fill */
- vswr_mode (handle,1); /* replace mode */
- vr_recfl (handle,rect); /* fill background */
- vsf_color (handle,1); /* restore black fill */
- vsf_interior (handle,0); /* hollow fill */
- /* draw left eye */
- v_ellipse (handle,xc-EYE_DX,yc-EYE_DY,8,11);
- /* draw right eye */
- v_ellipse (handle,xc+EYE_DX,yc-EYE_DY,8,11);
- vsf_interior (handle,1); /* restore solid fill */
- vswr_mode (handle,3); /* restore XOR mode */
- }
-
-
- /* Open the window
-
- Input:
- int use_grow_box : TRUE if a growing box has to be drawn
- on opening.
- */
-
- static void open_window (use_grow_box)
- int use_grow_box;
-
- {int win_x,win_y,win_width,win_height;
-
- if (whandle <= 0) /* Window closed ? */
- {
- /* Calculate size of window */
- /* from size of work area */
- if (wind_calc (WC_BORDER,win_components,
- work_x_origin,work_y_origin,
- WORK_WIDTH,WORK_HEIGHT,
- &win_x,&win_y,&win_width,&win_height) == 0)
- return; /* Error ? finished */
- /* Create window */
- whandle = wind_create (win_components,0,0,win_width,win_height);
- if (whandle <= 0) return; /* Error ? finished */
-
- if (use_grow_box) /* Growing box */
- graf_growbox (work_x_origin + WORK_WIDTH/2,
- work_y_origin + WORK_HEIGHT/2,1,1,
- work_x_origin,work_y_origin,
- WORK_WIDTH,WORK_HEIGHT);
-
- if (win_components & NAME) /* Set name if requested */
- wind_set(whandle,WF_NAME,"eyes",0,0);
- /* Open the window */
- wind_open (whandle,win_x,win_y,win_width,win_height);
- }
- else /* Window already open */
- wind_set (whandle,WF_TOP,0,0,0,0); /* Set window to top */
-
- /* Set default attributes */
- vsf_interior (handle,1); /* Solid fill */
- vsf_color (handle,1); /* Fill with colour 1 */
- vswr_mode (handle,3); /* XOR mode */
- vsf_perimeter (handle,1); /* Perimeter visible */
- }
-
-
- /* Open the window and restore top window
-
- Input:
- int use_grow_box : TRUE if a growing box has to be drawn
- on opening.
- */
-
- static void open_back_window (use_grow_box)
- int use_grow_box;
-
- {int top_window,dummy;
-
- wind_update (BEG_UPDATE); /* Start updating window */
- /* What is the current top window ? */
- if (wind_get (0,WF_TOP,&top_window,&dummy,&dummy,&dummy) == 0)
- top_window = -1;
-
- open_window (use_grow_box); /* Try to open the window */
- /* Window open ? restore top window */
- if (whandle > 0 && top_window > 0)
- wind_set (top_window,WF_TOP,0,0,0,0);
-
- wind_update (END_UPDATE);
- }
-
-
- /* Close the window
-
- Input:
- int use_shrink_box : TRUE if a shrinking box has to be drawn
- on closing.
- */
-
- static void close_window (use_shrink_box)
- int use_shrink_box;
-
- {
- if (use_shrink_box) /* Draw shrinking box */
- graf_shrinkbox (work_x_origin + WORK_WIDTH/2,
- work_y_origin + WORK_HEIGHT/2,1,1,
- work_x_origin,work_y_origin,
- WORK_WIDTH,WORK_HEIGHT);
- wind_close (whandle); /* Close window */
- wind_delete (whandle); /* Clear handle */
- whandle = 0; /* Window closed */
- }
-
-
- /* Move whandle window, recalculate origin of work area
-
- Input:
- int x,y : new position of window
- */
-
- static void move_window (x,y)
- int x,y;
-
- {int win_x,win_y,win_width,win_height,dummy;
-
- wind_update (BEG_UPDATE);
- /* Calculate current position of window */
- wind_get (whandle,WF_CURRXYWH,&win_x,&win_y,&win_width,&win_height);
- /* Set new position of window */
- wind_set (whandle,WF_CURRXYWH,x,y,win_width,win_height);
- /* Recalculate position of work area */
- wind_get (whandle,WF_WORKXYWH,&work_x_origin,&work_y_origin,
- &dummy,&dummy);
- wind_update (END_UPDATE);
- }
-
-
- /* Test intersection of two rectangles
-
- Input:
- GRECT *rec1,*rec2 : pointer to structure of rectangles
-
- If the rectangles dont intersect, 0 is returned.
- If they intersect, *rec2 is the intersection of the rectangles
- and a value != 0 is returned.
- */
-
- static int rect_intersect (rec1,rec2)
- register GRECT *rec1,*rec2;
-
- {register int x,y,wi,hi;
-
- x = max (rec2->g_x,rec1->g_x);
- y = max (rec2->g_y,rec1->g_y);
- wi = min (rec2->g_x + rec2->g_w,rec1->g_x + rec1->g_w);
- hi = min (rec2->g_y + rec2->g_h,rec1->g_y + rec1->g_h);
-
- rec2->g_x = x;
- rec2->g_y = y;
- rec2->g_w = wi - x;
- rec2->g_h = hi - y;
-
- return (((wi > x) && (hi > y)));
- }
-
-
- /* Redraw window
-
- Input:
- int all : TRUE if face and eyes have to be redrawn.
- FALSE if only eyes have to be redrawn.
- */
-
- static void redraw_window (all)
- int all;
-
- {GRECT box,work;
- int covered,clip[4];
- int x,y,dummy;
- int win_x,win_y,win_width,win_height;
- static unsigned int covered_count = 0;
-
- if (whandle <= 0) return; /* No window open ? finished */
-
- wind_update (BEG_UPDATE);
- /* Get position and size of work area */
- wind_get (whandle,WF_WORKXYWH,&work.g_x,&work.g_y,
- &work.g_w,&work.g_h);
- /* Get position and size of first rectangle */
- wind_get (whandle,WF_FIRSTXYWH,&box.g_x,&box.g_y,
- &box.g_w,&box.g_h );
- /* Window may be totally covered */
- if (box.g_w <= 0 && box.g_h <= 0)
- covered_count++;
- else
- covered_count = 0;
-
- if (covered_count > 2) /* If more than 2 times totally covered */
- { /* try to find a free area to move to */
- x = desk_work[0] + RAND() % (desk_size[0] - (WORK_WIDTH >> 1));
- y = desk_work[1] + RAND() % (desk_size[1]- (WORK_HEIGHT >> 1));
- /* Test height of eyes */
- covered = wind_find (x + (WORK_WIDTH >> 1),
- y + (WORK_HEIGHT >> 1) - EYE_DY);
-
- if (covered == 0) /* This location not covered ? */
- { /* Calculate size of window */
- /* from size of work area */
- wind_calc (WC_BORDER,win_components,x,y,WORK_WIDTH,WORK_HEIGHT,
- &win_x,&win_y,&win_width,&win_height);
- /* Set window to new position */
- wind_set (whandle,WF_CURRXYWH,win_x,win_y,win_width,win_height);
- /* Recalculate work area */
- wind_get (whandle,WF_WORKXYWH,&work_x_origin,&work_y_origin,
- &dummy,&dummy);
- covered_count = 0; /* No longer covered */
- goto end_redraw;
- }
- }
- /* Window may be partly off screen */
- /* Recalculate width and height */
- work.g_w = min (work.g_w,desk_work[2]-work.g_x+1);
- work.g_h = min (work.g_h,desk_work[3]-work.g_y+1);
-
- graf_mouse (M_OFF,(MFORM *)0); /* Switch mouse off */
-
- while (box.g_w > 0 && box.g_h > 0) /* For all rectangles in list */
- {
- if (rect_intersect (&work,&box)) /* If intersection not empty */
- {
- clip[0] = box.g_x; /* Calculate clip rectangle */
- clip[1] = box.g_y;
- clip[2] = box.g_x + box.g_w - 1;
- clip[3] = box.g_y + box.g_h - 1;
-
- vs_clip (handle,1,clip); /* Set clip rectangle */
-
- if (all) /* Redraw everything ? Draw background */
- face ();
- /* If last position valid and not */
- /* all to redraw: clear old position */
- if (!all && last_eye.left_dx != NOT_VALID)
- eyes (&last_eye);
-
- eyes (&new_eye); /* Draw new position */
- }
- /* Get nect rectangle from list */
- wind_get (whandle,WF_NEXTXYWH,&box.g_x,&box.g_y,&box.g_w,&box.g_h);
- }
- graf_mouse (M_ON,(MFORM *)0); /* Switch mouse on */
- vs_clip (handle,1,desk_work); /* Reset to maximum clip rectangle */
- save_position (); /* Save position of eyes */
-
- end_redraw:
-
- wind_update (END_UPDATE);
- }
-
-
- /* Handle message event
-
- Input:
- int pipe[8] : pointer to message buffer
-
- Value returned : TRUE if window was closed and program is
- not an accessory. Then the program has to be terminated.
- Otherwise FALSE is returned.
- */
-
- static int handle_message (pipe)
- int pipe[8];
-
- {register int this_is_open;
- int return_val = FALSE;
-
- /* check if window open and message is for this window */
- this_is_open = ((whandle >= 0) && (pipe[3] == whandle));
-
-
- switch (pipe[0])
- {
- case WM_REDRAW: /* Redraw window */
-
- if (this_is_open) /* Calculate new eye positions */
- { /* from mouse position */
- new_position (mouse_x,mouse_y);
- redraw_window (TRUE); /* Complete redraw */
- last_x = mouse_x; /* Save mouse position */
- last_y = mouse_y;
- }
- break;
-
- case WM_TOPPED: /* Set window to top */
- case WM_NEWTOP:
-
- if (this_is_open)
- {
- wind_update (BEG_UPDATE);
- wind_set (whandle,WF_TOP,0,0,0,0);
- wind_update (END_UPDATE);
- }
- break;
-
- case WM_CLOSED: /* Window closed (CLOSER activated) */
-
- if (this_is_open)
- {
- wind_update (BEG_UPDATE);
- close_window (TRUE);
- wind_update (END_UPDATE);
- auto_open = FALSE; /* Suppress automatic open */
- if (_app) /* For program set exit flag */
- return_val = TRUE;
- }
- break;
-
- case WM_MOVED: /* Move window (MOVER activated) */
-
- if (this_is_open)
- move_window (pipe[4],pipe[5]); /* Move to new position */
- break;
-
- case AC_OPEN: /* Accessory opened */
-
- if (pipe[4] == menu_id)
- {
- wind_update (BEG_UPDATE);
- open_window (TRUE); /* Open foreground window */
- wind_update (END_UPDATE);
- auto_open = TRUE; /* Activate automatic open */
- }
- break;
-
- case AC_CLOSE: /* Close accessory */
-
- if (pipe[3] == menu_id)
- whandle = 0; /* Just clear handle, nothing else */
- break;
- }
- return (return_val);
- }
-
-
- /* Wait for events
- */
-
- static void event_loop ()
-
- {register int ev_mflags,event;
- int kstate,key,clicks;
- int state,quit;
- int pipe[8];
- int win_x,win_y,win_width,win_height;
- static int wait_open = 0;
-
- quit = FALSE;
-
- do
- {
- ev_mflags = MU_MESAG; /* In all cases wait for message */
-
- /* Window closed and automatic open ? */
- if ((whandle <= 0) && auto_open)
- {
- /* Try to open background window after some time */
- if (++wait_open > 12) open_back_window (TRUE);
-
- if (whandle <= 0) /* Window not opened ? */
- ev_mflags |= MU_TIMER; /* Additionally wait for timer */
- else
- wait_open = 0; /* Clear wait count */
- }
-
- /* Window open ? Wait for button to move window and
- for timer to update position of eyes
- */
-
- if (whandle > 0) ev_mflags |= (MU_BUTTON | MU_TIMER);
- /* Now wait for event */
- event = evnt_multi (ev_mflags,
- 2,0x1,1, /* Mouse button event */
-
- 0,0,0,0,0, /* Mouse event 1 (not used) */
- 0,0,0,0,0, /* Mouse event 2 (not used) */
- pipe, /* Message event */
- 150,0, /* Timer event */
- &mouse_x,&mouse_y,&state,&kstate,&key,&clicks);
-
- #ifdef SHOW_ACTIVITY
-
- /* Invert a 2x2 pixel rectangle in the upper left corner
- of the screen on every occurance of an event
- */
-
- {int attrib[5];
- static int area[4] = { 0,0,2,2 };
-
-
- wind_update (BEG_UPDATE);
- vqf_attributes(handle,attrib); /* Inquire attributes */
- vs_clip (handle,1,area); /* Set clip reactangle */
- vswr_mode (handle,3); /* Set XOR mode */
- vsf_color (handle,1); /* Fill color 1 */
- vr_recfl (handle,area); /* Fill rectangle */
- vswr_mode (handle,attrib[3]); /* Restore write mode */
- vsf_color (handle,1); /* Restore fill colour */
- wind_update (END_UPDATE);
- }
- #endif
- /* Shortcut if nothing happened */
- if ( (event == MU_TIMER)
- && (mouse_x == last_x) && (mouse_y == last_y))
- continue;
- /* Handle messages */
- if (event & MU_MESAG) quit = handle_message (pipe);
-
- /* No window open ? no more actions */
- if (whandle <= 0) continue;
-
- /* Handle double-clicks (close window) */
- if ((event & MU_BUTTON) && state==1 && clicks==2)
- {
- wind_update (BEG_UPDATE);
- close_window (TRUE);
- wind_update (END_UPDATE);
- auto_open = FALSE; /* Suppress automatic open */
- if (_app) quit = TRUE; /* Quit for program */
- continue;
- }
- /* Handle single button down (move window) */
- if ((event & MU_BUTTON) && state == 1 && clicks==1)
- {
- wind_get (whandle,WF_CURRXYWH,&win_x,&win_y,
- &win_width,&win_height);
- graf_dragbox (win_width,win_height,win_x,win_y,
- desk_work[0],desk_work[1],
- desk_size[0]+WORK_WIDTH,desk_size[1]+WORK_HEIGHT,
- &win_x,&win_y);
- move_window (win_x,win_y);
- }
- /* Handle timer */
- if ( (event & MU_TIMER) /* Mouse and eye position changed ? */
- && (mouse_x != last_x || mouse_y != last_y)
- && (new_position (mouse_x,mouse_y)))
- {
- redraw_window (FALSE); /* Redraw eyes */
- last_x = mouse_x; /* Save last mouse position */
- last_y = mouse_y;
- }
- }
- while (!quit);
- }
-
-
- /* Main program
- */
-
- int main ()
-
- {register int i;
- int dummy;
- int work_in[11];
- int work_out[57];
-
- appl_id = appl_init (); /* Initialize application */
-
- if (appl_id >= 0)
- {
- for (i = 0; i < 10; i++) /* Initialize attributes */
- work_in[i] = 1;
- work_in[10] = 2; /* Use raster coordinates */
-
- handle = graf_handle (&dummy,&dummy,&dummy,&dummy);
-
- v_opnvwk (work_in,&handle,work_out);
- if (handle != 0)
- {
- /* Get desktop work-area as maximum clip rectangle */
- wind_get (0,WF_WORKXYWH,&(desk_work[0]),&(desk_work[1]),
- &(desk_size[0]),&(desk_size[1]));
- desk_work[2] = desk_work[0] + desk_size[0];
- desk_work[3] = desk_work[1] + desk_size[1];
-
- work_x_origin += desk_work[0]; /* Position own window within */
- work_y_origin += desk_work[1]; /* desktop work area */
-
- if (!_app) /* Accessory ? register menu entry */
- menu_id = menu_register (appl_id,MENU_ENTRY);
-
- graf_mouse (0,(MFORM *)0); /* Set mouse cursor to arrow */
-
- event_loop (); /* Event loop */
-
- v_clsvwk (handle);
- }
- appl_exit ();
- }
- return (0);
- }
-